#include <iostream>
#include <vector>
#include <unistd.h>
#include "Thread.hpp"

using namespace thread_ns;
using namespace std;

static int g_ticket = 1000;
const int nums = 4;

class ThreadData
{
public:
    ThreadData(int &ticket, const string &name, pthread_mutex_t &mutex)//锁记得引用!!!
        :_ticket(ticket),_name(name),_total(0),_mutex(mutex)
    {}
    ~ThreadData()
    {}

    int &_ticket;
    int _total;
    string _name;
    pthread_mutex_t &_mutex;
};

void *route(void *args)
{
    ThreadData *td = static_cast<ThreadData *>(args);
    while(true)
    {
        pthread_mutex_lock(&td->_mutex);
        if(td->_ticket > 0)
        {
            usleep(1000);
            cout << td->_name <<": "<< td->_ticket << endl;
            td->_ticket--;
            pthread_mutex_unlock(&td->_mutex);
            td->_total++;
        }
        else
        {
            pthread_mutex_unlock(&td->_mutex);
            break;
        }
    }
    return nullptr;
}

int main()
{
    pthread_mutex_t mutex;
    pthread_mutex_init(&mutex, nullptr);
    vector<pthread_t> threads;
    vector<ThreadData*> datas;
    for(int i=0; i<nums; i++)
    {
        char *name = new char[64];
        snprintf(name, 64, "thread-%d", i+1);
        ThreadData *td = new ThreadData(g_ticket, name, mutex);

        pthread_t tid;
        pthread_create(&tid, nullptr, route, (void*)td);
        threads.push_back(tid);

        datas.emplace_back(td);
    }

    for(auto &t:threads)
    {
        pthread_join(t, nullptr);
    }
    for(auto data: datas)
    {
        cout << data->_name << " total is: " << data->_total << endl;
    }
    
    cout << "thread ticket end" << endl;
    pthread_mutex_destroy(&mutex);
    return 0;
}

// pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
// pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
// void *taskA(void *args)
// {
//     string name = static_cast<char*>(args);
//     while(true)
//     {
//         sleep(1);
//         cout << "I am 线程A" << endl;
//         pthread_cond_signal(&cond);
//     }
//     return nullptr;
// }
// void *taskB(void *args)
// {
//     string name = static_cast<char*>(args);
//     while(true)
//     {
//         pthread_mutex_lock(&mutex);
//         pthread_cond_wait(&cond, &mutex);
//         cout << "I am 线程B" << endl;
//         pthread_mutex_unlock(&mutex);
//     }
//     return nullptr;
// }
// void StartA(vector<pthread_t> *tptr)
// {
//     pthread_t tid;
//     int n = pthread_create(&tid, nullptr, taskA, (void *)"thread-A");
//     if (n == 0)
//         cout << "create thread A success" << endl;
//     tptr->emplace_back(tid);
// }
// void StartB(vector<pthread_t> *tptr)
// {
//     pthread_t tid;
//     int n = pthread_create(&tid, nullptr, taskB, (void *)"thread-B");
//     if (n == 0)
//         cout << "create thread B success" << endl;
//     tptr->emplace_back(tid);
// }
// void WaitAll(vector<pthread_t> tptr)
// {
//     for (auto &thread : tptr)
//     {
//         pthread_join(thread, nullptr);
//     }
// }
// int main()
// {
//     vector<pthread_t> tids;
//     StartA(&tids);
//     StartB(&tids);
//     WaitAll(tids);
//     return 0;
// }

// static int g_ticket = 1000;
// const int nums = 4;

// class ThreadData
// {
// public:
//     ThreadData(int &ticket, const string &name, pthread_mutex_t &mutex)//锁记得引用!!!
//         :_ticket(ticket),_name(name),_total(0),_mutex(mutex)
//     {}
//     ~ThreadData()
//     {}

//     int &_ticket;
//     int _total;
//     string _name;
//     pthread_mutex_t &_mutex;
// };

// void route(ThreadData *td)
// {
//     while(true)
//     {
//         pthread_mutex_lock(&td->_mutex);
//         if(td->_ticket > 0)
//         {
//             usleep(1000);
//             cout << td->_name <<": "<< td->_ticket << endl;
//             td->_ticket--;
//             pthread_mutex_unlock(&td->_mutex);
//             td->_total++;
//         }
//         else
//         {
//             pthread_mutex_unlock(&td->_mutex);
//             break;
//         }
//     }
// }

// int main()
// {
//     pthread_mutex_t mutex;
//     pthread_mutex_init(&mutex, nullptr);
//     vector<Thread<ThreadData*>> threads;
//     vector<ThreadData*> datas;
//     for(int i=0; i<nums; i++)
//     {
//         char *name = new char[64];
//         snprintf(name, 64, "thread-%d", i+1);
//         ThreadData *td = new ThreadData(g_ticket, name, mutex);
//         threads.emplace_back(route, td, name);
//         datas.emplace_back(td);
//     }
//     for(auto &t:threads)
//     {
//         t.Start();
//     }

//     for(auto &t:threads)
//     {
//         t.Join();
//     }
//     for(auto &data: datas)
//     {
//         cout << data->_name << " total is: " << data->_total << endl;
//     }
//     pthread_mutex_destroy(&mutex);
//     return 0;
// }

// void Print(string name)
// {
//     cout << "I am " << name <<endl;
// }
// int main()
// {
//     Thread td(Print, "thread-a");
//     td.Start();
//     td.Join();
//     return 0;
// }